/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.cef.entity.accessor.entity;

import com.inspur.edp.cef.entity.accessor.base.IAccessor;
import com.inspur.edp.cef.entity.accessor.entity.IChildAccessor;
import com.inspur.edp.cef.entity.accessor.entity.IEntityAccessor;
import com.inspur.edp.cef.entity.accessor.entity.RootEntityAccessor;
import com.inspur.edp.cef.entity.dependenceTemp.DataValidator;
import com.inspur.edp.cef.entity.entity.ICefData;
import com.inspur.edp.cef.entity.entity.IEntityData;
import com.inspur.edp.cef.entity.entity.IEntityDataCollection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public abstract class AccessorCollection implements IEntityDataCollection {

  //TODO: 生成的子类构造函数里加上collection属性, 这里就不需要public
  //protected IEntityAccessor Parent { get; private set; }
  private IEntityAccessor privateParent;

  public final IEntityAccessor getParent() {
    return privateParent;
  }

  public final void setParent(IEntityAccessor value) {
    privateParent = value;
  }

  public AccessorCollection(IEntityAccessor belongEntity) {
    setParent(belongEntity);
  }

  private java.util.LinkedHashMap<String, IEntityData> dict = new java.util.LinkedHashMap<String, IEntityData>();

//	public final java.util.Iterator<IEntityData> GetEnumerator()
//	{

//		{

//		}
//	}

  //	private java.util.Iterator GetEnumerator()
//	{
//		return GetEnumerator();
//	}
  public int getCount() {
    return dict.size();
  }

  protected void beforeAdd(IEntityData item) {
  }

  private void fireItemAdded(IEntityData item) {
    if (getParent() == null) {
      return;
    }

    IAccessor tempVar = getParent().getRoot();

    RootEntityAccessor rootAccessor = (RootEntityAccessor) ((tempVar instanceof RootEntityAccessor)
        ? tempVar : null);
    if (rootAccessor == null) {
      return;
    }
    rootAccessor
        .fireChildAdded((IChildAccessor) ((item instanceof IChildAccessor) ? item : null), this);
  }

  public final void innerAdd(IEntityData item) {
    if (item instanceof IChildAccessor) {
      ((IChildAccessor) item).setParent(getParent());
    }
    dict.put(item.getID(), item);
  }

  public final void innerDelete(String id) {
    dict.remove(id);
  }

  protected Collection<IEntityData> innerGetAll() {
    return dict.values();
  }

  protected void beforeClear() {
  }

  public final void clear() {
    beforeClear();
    List<IEntityData> datas = new ArrayList<>(dict.values());
    for (IEntityData data : datas) {
      beforeRemove(data);
    }
    dict.clear();
    for (IEntityData data : datas) {
      fireItemRemoved(data);
    }
  }

  public final boolean contains(IEntityData item) {
    return dict.containsKey(item.getID());
  }

  protected void beforeRemove(IEntityData item) {
  }

  public final boolean remove(IEntityData item) {
    DataValidator.checkForNullReference(item, "item");
    return remove(item.getID());
  }

  private void fireItemRemoved(IEntityData item) {
    if (getParent() == null) {
      return;
    }
    IAccessor tempVar = getParent().getRoot();

    RootEntityAccessor rootAccessor = (RootEntityAccessor) ((tempVar instanceof RootEntityAccessor)
        ? tempVar : null);
    if (rootAccessor == null) {
      return;
    }
    rootAccessor
        .fireChildRemoved((IChildAccessor) ((item instanceof IChildAccessor) ? item : null), this);
  }

  public boolean getIsReadOnly() {
    return false;
  }

  public IEntityData getItem(String id) {
    return dict.get(id);
  }
//		public void setItem(String id, IEntityData value)
//		{dict.put(id,value);}


  public final IEntityData tryGet(String id) {
    IEntityData result = dict.get(id);
    return result;
  }

  public abstract IChildAccessor createInstance();

  public final void copyTo(IEntityData[] array, int arrayIndex) {
    int index = 0;
    for (Map.Entry<String, IEntityData> entry : dict.entrySet()) {
      array[index] = entry.getValue();
      index++;
    }
  }

  public final boolean remove(String id) {
    DataValidator.checkForNullReference(id, "id");

    IEntityData item = dict.get(id);
    beforeRemove(item);

    dict.remove(item.getID());
    fireItemRemoved(item);
    return true;
  }

  public final boolean contains(String id) {
    DataValidator.checkForNullReference(id, "id");
    return dict.containsKey(id);
  }

  protected abstract AccessorCollection createNewObject();

  public final AccessorCollection copy(IEntityAccessor parent) {
    AccessorCollection newCollection = (AccessorCollection) createNewObject();
    newCollection.setParent(parent);
    copyDict(newCollection, parent);
    return newCollection;
  }

  private void copyDict(AccessorCollection newCollection, IEntityAccessor parent) {
    for (Map.Entry<String, IEntityData> enriy : dict.entrySet()) {
      IEntityData newItem = (IEntityData) enriy.getValue().copy();
      if (newItem instanceof IChildAccessor) {
        IChildAccessor newChild = (IChildAccessor) newItem;
        newChild.setParent(parent);
      }
      newCollection.dict.put(enriy.getKey(), newItem);
    }
  }

  //region ICollection接口需要但未实现的方法

  @Override
  public void setItem(String s, IEntityData iEntityData) {
    throw new UnsupportedOperationException();
  }

  @Override
  public int size() {
    return dict.size();

  }

  @Override
  public boolean isEmpty() {
    return dict.isEmpty();

  }

  @Override
  public boolean contains(Object o) {
    throw new UnsupportedOperationException();

  }

  @Override
  public Iterator<IEntityData> iterator() {
    return new Iterator<IEntityData>() {
      private Iterator<Map.Entry<String, IEntityData>> index = dict.entrySet().iterator();

      @Override
      public boolean hasNext() {
        return index.hasNext();
      }

      @Override
      public IEntityData next() {
        return index.next().getValue();
      }
    };
  }

  @Override
  public Object[] toArray() {
    return dict.values().toArray();

  }

  @Override
  public <T> T[] toArray(T[] a) {
    throw new UnsupportedOperationException();

  }

  @Override
  public boolean add(IEntityData item) {
    if (item instanceof IChildAccessor) {
      ((IChildAccessor) item).setParent(getParent());
    }
    beforeAdd(item);
    dict.put(item.getID(), item);
    fireItemAdded(item);
    return true;
  }

  @Override
  public boolean remove(Object o) {
    dict.remove(o);
    return true;
  }

  @Override
  public boolean containsAll(Collection<?> c) {
    throw new UnsupportedOperationException();

  }

  @Override
  public boolean addAll(Collection<? extends IEntityData> c) {
    Objects.requireNonNull(c);

    for (IEntityData d : c) {
      add(d);
    }
    return true;
  }

  @Override
  public boolean removeAll(Collection<?> c) {
    throw new UnsupportedOperationException();
  }

  @Override
  public boolean retainAll(Collection<?> c) {
    throw new UnsupportedOperationException();
  }
  //endregion
}
